home *** CD-ROM | disk | FTP | other *** search
- # include <stdio.h>
- # include <ingres.h>
- # include <pv.h>
- # include <aux.h>
- # include <access.h>
- # include <batch.h>
- # include <lock.h>
- # include <opsys.h>
- # include <func.h>
- # include <version.h>
- # include <symbol.h>
- # include <catalog.h>
- # include <btree.h>
- # include <sccs.h>
- # include <errors.h>
-
- SCCSID(@(#)modify.c 8.8 5/7/85)
-
- extern short tTdbu[];
- extern int modify();
- extern int null_fn();
- extern char *iocv();
-
- struct fn_def ModifyFn =
- {
- "MODIFY",
- modify,
- null_fn,
- null_fn,
- NULL,
- 0,
- tTdbu,
- 100,
- 'Z',
- 0
- };
-
- /*
- ** MODIFY -- converts any relation to the specified
- ** storage structure
- **
- ** arguments:
- ** 0 - relation name
- ** 1 - storage structure ("heap", "cheap", "hash", "chash",
- ** "isam", "cisam")
- ** 2 - "name" for attribute names, or "num" for numbers
- ** 3 - key1
- ** 4 - key2
- ** .
- ** .
- ** i - null
- ** i+1 - option name (e.g., "fillfactor")
- ** i+2 - option value
- ** .
- ** .
- **
- ** If all the options default, parameter i -> pc are omitted.
- ** If no keys are provided, parameter 2 is omitted.
- */
-
- int F_fac, Mn_pages, Mx_pages;
- char Lid[MAXLID][MAXNAME];
- int NLidKeys;
- int LidKey[MAXLID];
-
- struct modtab
- {
- char *type;
- char newrelspec;
- char yeskeys;
- char sortit;
- char yes_seq;
- int f_fac;
- int mn_pages;
- int mx_pages;
- };
-
-
- struct modtab Modtab[] =
- {
- /* type spec keys sort seq ffac min max */
-
- "heap", M_HEAP, FALSE, FALSE, FALSE, 0, 0, 0,
- "cheap", -M_HEAP,FALSE, FALSE, FALSE, 0, 0, 0,
- "hash", M_HASH, TRUE, TRUE, FALSE, 50, 10, -1,
- "chash", -M_HASH,TRUE, TRUE, FALSE, 75, 1, -1,
- "isam", M_ISAM, TRUE, TRUE, FALSE, 80, 0, 0,
- "cisam", -M_ISAM,TRUE, TRUE, FALSE, 100, 0, 0,
- "heapsort", M_HEAP, TRUE, TRUE, TRUE, 0, 0, 0,
- "cheapsort", -M_HEAP,TRUE, TRUE, TRUE, 0, 0, 0,
- "truncated", M_TRUNC,FALSE, FALSE, FALSE, 0, 0, 0,
- "ordered", M_ORDER,TRUE, FALSE, FALSE, 0, 0, 0,
- 0
- };
-
- struct mod_info
- {
- char outfile[MAXNAME + 4]; /* result file filled by ksort */
- char formfile[MAXNAME + 4]; /* file with descriptor for ksort */
- char infile[MAXNAME + 4]; /* input file for ksort (relation itself */
- char reltemp[MAXNAME + 4]; /* file holding new relation */
- char spfile[MAXNAME + 4], spflag; /* isam spool file for overflow */
- char btree[MAXNAME + 4]; /* file holding temporary btree structure */
- char temp_sort[MAXNAME + 4]; /* file holding result of special isam
- ** required when ordering on a field
- */
- };
-
- struct mod_info Mod_info;
-
- extern DESC Btreesec;
- extern int Btree_fd;
-
-
-
- modify(pc, pv)
- int pc;
- PARM *pv;
- {
- register int i, j;
- register char *rname;
- register struct modtab *mp;
- struct modtab *p;
- int sorted, dim;
- DESC dold, dnew;
- long temptid;
- extern int Noupdt;
- extern DESC Attdes;
- struct attribute atttup, attkey;
- TID tid;
- int lidkey, numatts;
- extern char *trim_relname();
-
-
- # ifdef xZTR1
- if (tTf(34, -1))
- {
- printf("enter modify\n");
- prvect(pc, pv);
- }
- # endif
-
- pv[pc].pv_val.pv_str = NULL;
-
- /* check for nice parameters */
- if (pc < 2)
- syserr("MODIFY: pc %d", pc);
-
- /* save relation name for error messages */
- rname = (pv++)->pv_val.pv_str; /* *pv now pointes to storage spec */
-
- /* check for good relation */
- i = openr(&dold, OR_READ, rname);
- if (i == AMOPNVIEW_ERR)
- return (error(NOMODVIEW, rname, 0));
- if (i > 0)
- /* reln does not exist */
- return (error(NOREL, rname, 0));
- else if (i < 0)
- syserr("MODIFY: openr (%.14s) %d", rname, i);
- /* can only modify a relation you own and isn't a sys rel */
-
- if (!bequal(Usercode, dold.reldum.relowner, UCODE_SZ))
- {
- i = NOOWN;
- }
- if ((dold.reldum.relstat & S_CATALOG) && Noupdt)
- {
- i = NOMODSYSREL;
- }
- if (i)
- {
- closer(&dold);
- return (error(i, rname, 0));
- }
-
- /*
- ** Form descriptor for new relation. Here we need to
- ** separate the pages from the old and new relations.
- ** Since pages are identified by the TID of the relation
- ** relation tuple, both old and new have the same identifiers.
- ** To avoid this problem, a special TID is hand crafted for
- ** the new relation.
- */
- bmove(&dold, &dnew, sizeof dnew);
- dnew.reltid.s_tupid.line_id = (char) -2; /* choose impossible reltid */
- /* assume new relation isn't ordered */
- if (dold.reldum.reldim)
- {
- dnew.reldum.relatts -= dold.reldum.reldim;
- dnew.reldum.relwid -= dold.reldum.reldim * LIDSIZE;
- dnew.reldum.reldim = 0;
- }
-
- /* In case of an interrupt from a previous modify,
- ** there might be pages around. Get rid of them.
- */
- cleanrel(&dnew);
-
- ingresname(dold.reldum.relid, dold.reldum.relowner, Mod_info.infile);
- dim = 0;
- NLidKeys = 0;
-
- /* scan for entry in relspec table */
- for (mp = Modtab; mp->type; mp++)
- {
- if (bequal(mp->type, pv->pv_val.pv_str, 7) && bequal("ordered", pv->pv_val.pv_str, 7))
- {
- if ((dim = atoi(pv->pv_val.pv_str + 7)) <= 0 || dim > MAXLID)
- {
- closer(&dold);
- return(error(BADORDDIM, rname, iocv(dim), 0));
- }
- break;
- }
- if (sequal(mp->type, pv->pv_val.pv_str))
- break;
- }
-
- /* if not found, error */
- if (!mp->type)
- {
- closer(&dold);
- return (error(BADSTORAGE, rname, pv->pv_val.pv_str, 0)); /* bad relspec */
- }
-
- if (mp->newrelspec == M_ORDER && dold.reldum.relindxd == SECINDEX)
- /* can't order an index relation */
- {
- closer(&dold);
- return(error(NOORDINDX, rname,0));
- }
-
- if (mp->newrelspec == M_ORDER)
- {
- dnew.reldum.reldim = dim;
- for (i = 0; i < dim; ++i)
- {
- ++dnew.reldum.relatts;
- dnew.relxtra[dnew.reldum.relatts] = 0;
- dnew.reloff[dnew.reldum.relatts] = dnew.reldum.relwid;
- dnew.relfrmt[dnew.reldum.relatts] = INT;
- dnew.relfrml[dnew.reldum.relatts] = LIDSIZE;
- dnew.reldum.relwid += LIDSIZE;
- }
- concat(BTREE, Fileset, Mod_info.btree);
- create_btree(Mod_info.btree);
- dnew.btree_fd = Btree_fd;
- /* ok to order ascending/descending */
- mp->yes_seq = TRUE;
- }
- else
- {
- dnew.reldum.relspec = mp->newrelspec;
- if (dold.reldum.reldim)
- {
- dold.reldum.relatts -= dold.reldum.reldim;
- dold.reldum.relwid -= dold.reldum.reldim * LIDSIZE;
- dold.reldum.reldim = 0;
- closer(dold.relbtree);
- close(dold.btree_fd);
- }
- }
-
- if (dnew.reldum.relspec == M_TRUNC)
- dnew.reldum.relspec = M_HEAP;
-
- pv++; /* now points to first parameter */
-
- /* get the key domains information */
- if ((i = getkeys(&pv, rname, &dnew, mp)) > 0)
- {
- closer(&dold);
- return (i); /* user error */
- }
-
- j = 0;
- for (i = 0; i < NLidKeys; ++i)
- if (LidKey[i] > dold.reldum.relatts - dold.reldum.reldim)
- {
- j = 1;
- break;
- }
-
- if (!j && dold.reldum.reldim)
- /* treat old relation as if not ordered since lid field not needed */
- {
- dold.reldum.relatts -= dold.reldum.reldim;
- dold.reldum.relwid -= dold.reldum.reldim * LIDSIZE;
- dold.reldum.reldim = 0;
- closer(dold.relbtree);
- close(dold.btree_fd);
- }
-
- if (!dnew.reldum.reldim || !NLidKeys)
- {
- F_fac = mp->f_fac;
- Mn_pages = mp->mn_pages;
- Mx_pages = mp->mx_pages;
- }
- else
- /* set parameters to that of storage type of relation to be ordered */
- {
- for (p = Modtab; p->type; p++)
- if (dnew.reldum.relspec == p->newrelspec)
- break;
- F_fac = p->f_fac;
- Mn_pages = p->mn_pages;
- Mx_pages = p->mx_pages;
- }
-
- if (mp->newrelspec != M_ORDER)
- for (i = 0; i < dnew.reldum.reldim; ++i)
- Lid[i][0] = 0;
- else
- for (i = 1; i <= dnew.reldum.reldim; ++i)
- concat("lid", iocv(i), Lid[i-1]);
-
- /* get fillfactor and other options if any */
- if (i = getfill(&dnew, pv, rname, mp))
- {
- closer(&dold);
- return (i); /* user error */
- }
-
- /* check for duplicate attribute name */
- if (mp->newrelspec == M_ORDER)
- {
- opencatalog("attribute", OR_READ);
- setkey(&Attdes, &attkey, dnew.reldum.relid, ATTRELID);
- setkey(&Attdes, &attkey, dnew.reldum.relowner, ATTOWNER);
- numatts = dold.reldum.relatts - dold.reldum.reldim;
- for (i = 0; i < dnew.reldum.reldim; ++i)
- {
- setkey(&Attdes, &attkey, Lid[i], ATTNAME);
- if (getequal(&Attdes, &attkey, &atttup, &tid) == 0)
- {
- if (atttup.attid <= numatts)
- /* ok to duplicate attributes that will be removed */
- {
- closer(&dold);
- return(error(INVALIDATTR, rname, Lid[i], 0));
- }
- }
- }
- }
-
- /* lock the relation relation */
- if (Lockrel)
- {
- get_p_tid(&dold, &temptid);
- setrll(A_SLP, temptid, M_EXCL);
- }
-
- if (!dnew.reldum.reldim || NLidKeys > 0)
- /* compute new relation parameters & build descriptor */
- make_newrel(&dnew);
-
- if (sorted = ((mp->sortit || NLidKeys > 0) && (dold.reldum.reltups != 0)))
- {
- sortrel(&dold, &dnew);
- dold.reldum.relindxd = 0;
- }
-
- if (!dnew.reldum.reldim || NLidKeys > 0)
- /* physically create the new relation */
- if (formatpg(&dnew, dnew.reldum.relprim) != 0)
- syserr("modify: formatpg");
-
- /* clear relgiven field; if heap remove any keys */
- clearkeys(&dnew);
-
- if (abs(dnew.reldum.relspec) == M_HEAP)
- for (i = 1; i <= dnew.reldum.relatts; i++)
- dnew.relxtra[i] = 0;
-
- if (NLidKeys > 0 && dnew.reldum.relspec == M_ISAM)
- sort_isam(&dold, &dnew);
-
- if (mp->newrelspec != M_TRUNC)
- fill_rel(&dold, &dnew, sorted);
-
- closer(&dold); /* error return is impossible */
- if (abs(dnew.reldum.relspec) == M_ISAM && (!dnew.reldum.reldim || NLidKeys > 0))
- {
- j = dnew.reldum.reldim;
- dnew.reldum.reldim = 0;
- if (i = bldindex(&dnew))
- syserr("bldindex: %.14s %d", dnew.reldum.relid, i);
- dnew.reldum.reldim = j;
- unspool(&dold, &dnew);
- }
-
- /*
- ** New relation is now complete. The system relations need to
- ** be updated. First destroy all buffers with pages from the
- ** new relation.
- */
- if (i = cleanrel(&dnew))
- syserr("modify:clean new %d,%.14s", i, dnew.reldum.relid);
-
- fill_batch(&dold, &dnew);
-
- /*
- ** Close the file for the new relation. This must be
- ** done after the fill_batch in case we are modifing
- ** the attribute relation.
- */
- if (!dnew.reldum.reldim || NLidKeys > 0)
- close(dnew.relfp);
- dnew.relopn = 0;
- ruboff("modify");
- modupdate();
- if (mp->newrelspec == M_ORDER)
- {
- close(dnew.btree_fd);
- make_bsec(dnew.reldum.relid, dim);
- }
- rubon();
-
- if (Lockrel)
- unlrl(temptid);
-
- return (0);
- }
-
-
- /*
- ** GETKEYS - get key domains information
- **
- ** Parameters:
- ** ppv - parameter vector with info about keys
- ** relname - relation name
- ** d - new descriptor for the relation
- ** mp - mod table
- **
- ** Return Codes:
- ** 0 - ok
- ** >0 - error from modseqkey
- */
- getkeys(ppv, relname, d, mp)
- PARM **ppv;
- char *relname;
- register DESC *d;
- struct modtab *mp;
- {
- register PARM *pv;
- register char *cp;
- int namemode, sort_only, as_ds;
- int i, j, keyno, keywid;
- struct attribute attkey, atttup;
- struct index ikey, itup;
- TID tid;
- extern DESC Attdes, Inddes;
-
- pv = *ppv; /* copy list of params */
-
- if (mp->newrelspec != M_ORDER)
- /* zero key info (ordering does not change keyed fields) */
- for (i = 0; i <= d->reldum.relatts; i++)
- d->relxtra[i] = 0;
- for (i = 0; i <= d->reldum.relatts; ++i)
- d->relgiven[i] = 0;
-
- /* determine whether there are any keys at all */
- keywid = 0;
- keyno = 0;
- sort_only = FALSE;
- cp = pv->pv_val.pv_str;
-
- if (cp == (char *)NULL || *cp == (char *)NULL)
- {
- /* no key information. default as needed */
- if (mp->yeskeys && mp->newrelspec != M_ORDER)
- {
- cp = "\1"; /* default to first key */
- namemode = FALSE;
- }
- else
- pv++; /* point one to far */
- }
- else
- {
- /* check for name mode */
- if (namemode = sequal(cp, "name"))
- {
-
- /* check attribute names, and convert them to numbers */
- opencatalog("attribute", OR_READ);
- setkey(&Attdes, &attkey, Mod_info.infile, ATTRELID);
- setkey(&Attdes, &attkey, Usercode, ATTOWNER);
- }
- pv++; /* inc to next key */
- cp = (pv++)->pv_val.pv_str;
- }
-
- /* scan for attribute names */
- for (; cp != NULL; cp = (pv++)->pv_val.pv_str)
- {
- /* check for separator between keys & options */
- if (*cp == (char *)NULL)
- {
- pv++; /* point two past NULL */
- break;
- }
-
- if (NLidKeys >= d->reldum.reldim && mp->newrelspec == M_ORDER)
- {
- /* more than one field specified as ordering key */
- closeall(0l, 0l);
- return(error(TOOMANYORDKEYS, relname, 0));
- }
-
- if (namemode)
- {
- /* check for "sort only" attribute */
- if (*cp == '#')
- {
- cp++; /* inc to start of name */
- sort_only = TRUE;
- }
-
- /* check for ascending/descending modifier */
- if ((as_ds = modseqkey(cp, relname, mp->yes_seq)) > 0)
- return (as_ds); /* error */
-
- setkey(&Attdes, &attkey, cp, ATTNAME);
- i = getequal(&Attdes, &attkey, &atttup, &tid);
- if (i < 0)
- syserr("MODIFY: geteq(att) %d", i);
- if (i > 0)
- {
- closeall(0l, 0l);
- return (error(INVALIDATTR, relname, cp, 0)); /* bad att name */
- }
- i = atttup.attid;
- if (i > d->reldum.relatts)
- {
- /* attempting to key on lid field which will be
- ** removed
- */
- closeall(0l,0l);
- return(error(ATTRREMV, relname, cp, 0));
- }
- }
- else
- {
- i = *cp;
- as_ds = 0;
- }
-
- keyno++;
- /* add new key to descriptor */
- if (mp->newrelspec == M_ORDER)
- LidKey[NLidKeys++] = i;
- if (!sort_only && mp->newrelspec != M_ORDER)
- {
- d->relxtra[i] = keyno;
- keywid += (d->relfrml[i] & I1MASK);
- }
- if (d->relgiven[i])
- {
- closeall(0l, 0l);
- return (error(DUPKEY, relname, cp, 0)); /* duplicate attribute */
- }
- d->relgiven[i] = as_ds == 0 ? keyno : -keyno;
- }
- pv--; /* back up one to point to "-1" terminator */
-
-
- if (abs(d->reldum.relspec) == M_ISAM && keywid > (MAXTUP / 2 - 4))
- {
- closeall(0l, 0l);
- return (error(TOOWIDEISAM, relname, iocv(keywid), 0));
- }
-
- /* if a heap, there can be no keys */
- if (!mp->yeskeys && keyno != 0)
- {
- closeall(0l, 0l);
- return (error(NOKEYSHEAP, relname, mp->type, 0)); /* no keys allowed on heap */
- }
- /* fill out default sort on remainder of keys */
- if (mp->yeskeys)
- for (i = 1; i <= d->reldum.relatts; i++)
- if (d->relgiven[i] == 0)
- d->relgiven[i] = ++keyno;
- *ppv = pv;
- return (0);
- }
-
-
- /*
- ** MODSEQKEY - verify that sequence specified is valid
- **
- ** Parameters:
- ** domain - list of domains
- ** relname - relation name
- ** seq_ok - whether it is ok to specify the sequence
- ** ascending or descending
- **
- ** Return Codes:
- ** 0 - ok
- ** > 0 - error in sequence specified
- **
- ** Called by:
- ** getkeys
- */
- modseqkey(domain, relname, seq_ok)
- char *domain;
- char *relname;
- int seq_ok;
- {
- register char *cp, c;
- register int ret;
-
- ret = 0;
-
- for (cp = domain; c = *cp++; )
- if (c == ':')
- break;
-
- if (c != '\0')
- {
- /* replace ":" with null */
- *(cp - 1) = '\0';
-
- /* verify sequence is valid */
- if (!seq_ok)
- {
- closeall(0l, 0l);
- ret = error(BADSEQSPEC, relname, cp, domain, 0);
- }
- else if (sequal("descending", cp) || sequal("d", cp))
- ret = -1;
- else if (!(sequal("ascending", cp) || sequal("a", cp)))
- {
- closeall(0l, 0l);
- ret = error(INVALIDSEQ, relname, cp, domain, 0);
- }
- }
-
- return (ret);
- }
- /*
- ** GETFILL -- Get fill factor and minimum pages parameters
- ** from argument list, convert them from ascii to integer
- ** and store them in global variables. If the global
- ** variable for the corresponding parameter is zero,
- ** it means that that parameter is not allowed and an
- ** error is generated.
- */
-
- /*ARGSUSED*/
- getfill(d, pv, rel, mp)
- DESC *d;
- register PARM *pv;
- char *rel;
- struct modtab *mp;
- {
- register char *p1;
- register int err;
- char *p2;
- int i, j;
- int fill_flag, min_flag, max_flag, lid_flag[MAXLID];
-
- err = 0;
- fill_flag = min_flag = max_flag = FALSE;
- for (i = 0; i < d->reldum.reldim; ++i)
- lid_flag[i] = FALSE;
-
- while ((p1 = (pv++)->pv_val.pv_str) != (char *)NULL)
- {
- p2 = (pv++)->pv_val.pv_str;
- if (sequal(p1, "fillfactor"))
- {
- if (F_fac == 0 || fill_flag)
- {
- err = NOTALLOWED;
- break;
- }
- p1 = p2;
- F_fac = atoi(p1);
- if (F_fac > 100 || F_fac < 1)
- {
- err = FILLBOUND;
- break;
- }
- fill_flag = TRUE;
- continue;
- }
- if (sequal(p1, "minpages"))
- {
- if (Mn_pages == 0 || min_flag)
- {
- err = NOTALLOWED;
- break;
- }
- p1 = p2;
- Mn_pages = atoi(p1);
- if (Mn_pages < 1)
- {
- err = MINPGBOUND;
- break;
- }
- if (max_flag && (Mn_pages > Mx_pages))
- {
- err = MINGTMAX;
- break;
- }
- min_flag = TRUE;
- continue;
- }
- if (sequal(p1, "maxpages"))
- {
- if (Mx_pages == 0 || max_flag)
- {
- err = NOTALLOWED;
- break;
- }
- p1 = p2;
- Mx_pages = atoi(p1);
- if (Mx_pages < 1)
- {
- err = MAXPGBOUND;
- break;
- }
- if (min_flag && (Mn_pages > Mx_pages))
- {
- err = MINGTMAX;
- break;
- }
- max_flag = TRUE;
- continue;
- }
- for ( i = 1; i <= d->reldum.reldim && !err; ++i)
- if (sequal(p1, ztack("lid", iocv(i))))
- {
- if (lid_flag[i-1] || *Lid[i-1] == (char *)NULL)
- {
- err = NOTALLOWED;
- break;
- }
- for (j = 0; j < d->reldum.reldim; ++j)
- if (i - 1 != j && sequal(p2, Lid[j]) && lid_flag[j])
- {
- err = NOTALLOWED;
- break;
- }
- p1 = p2;
- smove(p1, Lid[i - 1]);
- lid_flag[i - 1] = TRUE;
- break;
- }
- if (err)
- break;
- if (i <= d->reldum.reldim)
- continue;
- err = NEEDFILL;
- break;
- }
- if (err)
- {
- closeall(0l, 0l);
- return (error(err, rel, p1, 0));
- }
- return (0);
- }
- /*
- ** MAKE_NEWREL -- Create a file for the modified relation
- ** and build one or more primary pages for the
- ** relation based on its storage structure and the
- ** number of tuples it must hold.
- */
-
- make_newrel(desc)
- register DESC *desc;
- {
- register int tups_p_page;
- int width;
-
- concat(MODTEMP, Fileset, Mod_info.reltemp);
- close(creat(Mod_info.reltemp, FILEMODE));
- if ((desc->relfp = open(Mod_info.reltemp, O_RDWR)) < 0)
- syserr("MAKE_NEWREL: open %.14s %d", Mod_info.reltemp, desc->relfp);
- desc->relopn = (desc->relfp + 1) * -5;
- desc->reldum.relprim = 1;
- if (abs(desc->reldum.relspec) == M_HASH && F_fac > 0 && Mn_pages > 0)
- {
- /*
- ** Determine the number of primary pages. The following
- ** first determines the number of tuples/page which the
- ** relation should have in order to get the requested
- ** fillfactor. Then that number is divided into the
- ** number of tuples to get the number of primary pages.
- ** To avoid round off, it must guaranteed that the
- ** number of tuples per page must be at least 1.
- **
- ** primary_pages = #tuples / (#tuples/page * fillfactor)
- */
- width = desc->reldum.relwid + 2 - LIDSIZE * desc->reldum.reldim;
- tups_p_page = (((MAXTUP+2) / width) * F_fac) / 100;
- if (tups_p_page == 0)
- tups_p_page = 1;
- /* we add one to simulate a ceiling function */
- desc->reldum.relprim = desc->reldum.reltups / tups_p_page + 1;
- if (desc->reldum.relprim < Mn_pages)
- desc->reldum.relprim = Mn_pages;
- if (Mx_pages > 0 && desc->reldum.relprim > Mx_pages)
- desc->reldum.relprim = Mx_pages;
- # ifdef xZTR1
- if (tTf(36, 0))
- printf("using %ld prim pages\n", desc->reldum.relprim);
- # endif
- }
- desc->reldum.reltups = 0;
- return (0);
- }
- /*
- ** SORTREL - Call KSORT to sort the given relation. SORTREL
- ** sets up the descriptor struct specifying the sort
- ** keys and tells KSORT whether or not the hash key should
- ** be included as a sort key.
- */
-
- sortrel(odesc, desc)
- DESC *odesc;
- register DESC *desc;
- {
- extern char *Pathname;
- register int i;
- char buf[50];
- DESC tempdesc;
- char *temp;
- int len;
- short smalli;
-
- concat(ISAM_SORTED, Fileset, Mod_info.outfile);
- if (close(creat(Mod_info.outfile, FILEMODE)))
- syserr("SORTREL: creat %.14s", Mod_info.outfile);
- bmove(odesc, &tempdesc, sizeof *odesc);
- for (i = 1; i <= desc->reldum.relatts; ++i)
- /* set up temporary descriptor for ksort with new keyed fields */
- {
- tempdesc.relxtra[i] = desc->relxtra[i];
- tempdesc.relgiven[i] = desc->relgiven[i];
- }
-
- if (abs(desc->reldum.relspec) == M_HASH && !desc->reldum.reldim)
- {
- /* sort on hash bucket first, (if ordering sort on ordering key, not bucket) */
- tempdesc.relgiven[0] = 1;
- for (i = 1; i <= desc->reldum.relatts; i++)
- tempdesc.relgiven[i]++;
- }
-
- # ifdef xZTR2
- if (tTf(36, 4))
- {
- printf("sortrel: ");
- printdesc(&tempdesc);
- }
- # endif
-
- /* flush buffers used by modify so that ksort can't look at them */
- flush_rel(desc, TRUE);
- resetacc(NULL);
-
- /* copy Fileset so it can't get trashed */
-
- len = length(Fileset) + 1;
- temp = (char *) need(Qbuf, len);
- bmove(Fileset, temp, len);
-
- initp();
- setp(PV_STR, temp);
- setp(PV_STR, Mod_info.infile);
- setp(PV_STR, Mod_info.outfile);
-
- /* Descriptor for new relation */
- setp(PV_STR, tempdesc.reldum.relid);
- setp(PV_STR, tempdesc.reldum.relowner);
- setp(PV_INT, tempdesc.reldum.relspec);
- setp(PV_INT, tempdesc.reldum.relindxd);
- setp(PV_INT, tempdesc.reldum.relstat2);
- setp(PV_INT, tempdesc.reldum.relstat);
- setp(PV_INT, (short) tempdesc.reldum.relsave);
- setp(PV_INT, (short) tempdesc.reldum.reltups);
- setp(PV_INT, tempdesc.reldum.relatts);
- setp(PV_INT, tempdesc.reldum.relwid);
- setp(PV_INT, (short) tempdesc.reldum.relprim);
- setp(PV_INT, (short) tempdesc.reldum.relfree);
- setp(PV_INT, (short) tempdesc.reldum.relstamp);
- setp(PV_INT, tempdesc.reldum.reldim);
-
- setp(PV_STR, tempdesc.relvname);
- setp(PV_INT, tempdesc.relfp);
- setp(PV_INT, tempdesc.relopn);
- setp(PV_INT, (short) tempdesc.reladds);
- setp(PV_INT, tempdesc.reltid.ltid);
- for (i = 0; i <= tempdesc.reldum.relatts; ++i)
- {
- smalli = (short) tempdesc.reloff[i];
- setp(PV_INT, smalli);
- smalli = (short) tempdesc.relfrmt[i];
- setp(PV_INT, smalli);
- smalli = (short) tempdesc.relfrml[i];
- setp(PV_INT, smalli);
- smalli = (short) tempdesc.relxtra[i];
- setp(PV_INT, smalli);
- smalli = (short) tempdesc.relgiven[i];
- setp(PV_INT, smalli);
- }
-
- if (tempdesc.reldum.reldim > 0)
- {
- setp(PV_STR, odesc->relbtree->reldum.relid);
- setp(PV_STR, odesc->relbtree->reldum.relowner);
- setp(PV_INT, odesc->relbtree->reldum.relspec);
- setp(PV_INT, odesc->relbtree->reldum.relindxd);
- setp(PV_INT, odesc->relbtree->reldum.relstat2);
- setp(PV_INT, odesc->relbtree->reldum.relstat);
- setp(PV_INT, (short) odesc->relbtree->reldum.relsave);
- setp(PV_INT, (short) odesc->relbtree->reldum.reltups);
- setp(PV_INT, odesc->relbtree->reldum.relatts);
- setp(PV_INT, odesc->relbtree->reldum.relwid);
- setp(PV_INT, (short) odesc->relbtree->reldum.relprim);
- setp(PV_INT, (short) odesc->relbtree->reldum.relfree);
- setp(PV_INT, (short) odesc->relbtree->reldum.relstamp);
- setp(PV_INT, odesc->relbtree->reldum.reldim);
-
- setp(PV_STR, odesc->relbtree->relvname);
- setp(PV_INT, odesc->relbtree->relfp);
- setp(PV_INT, odesc->relbtree->relopn);
- setp(PV_INT, (short) odesc->relbtree->reladds);
- setp(PV_INT, odesc->relbtree->reltid.ltid);
-
- for (i = 0; i <= odesc->relbtree->reldum.relatts; ++i)
- {
- smalli = (short) odesc->relbtree->reloff[i];
- setp(PV_INT, smalli);
- smalli = (short) odesc->relbtree->relfrmt[i];
- setp(PV_INT, smalli);
- smalli = (short) odesc->relbtree->relfrml[i];
- setp(PV_INT, smalli);
- smalli = (short) odesc->relbtree->relxtra[i];
- setp(PV_INT, smalli);
- smalli = (short) odesc->relbtree->relgiven[i];
- setp(PV_INT, smalli);
- }
- }
-
- call(mdKSORT, NULL);
-
- /* flush buffers used by ksort so that modify can't look at them */
- flush_rel(desc, TRUE);
- resetacc(NULL);
-
- # ifdef xZTR1
- if (tTf(36,9))
- printf("SORTREL: done calling ksort\n");
- #endif
- return (0);
- }
- /*
- ** SORT_ISAM -- Sorts an isam relation back to its original order
- ** so that it will be inserted into the relation in the proper order.
- ** It is presently not in order because it has been sorted according
- ** to a specified field for ordering.
- */
- sort_isam(sdesc, desc)
- DESC *sdesc;
- DESC *desc;
- {
- long lid[MAXLID];
- register int i, j, k;
- char tup_buf[MAXTUP], last_tup[MAXTUP], *dp, *sp;
- FILE *sfp, *fp;
- TID tid, tidpos;
- DESC tempdesc;
- int w;
-
- if (desc->reldum.reldim > 0)
- Btree_fd = desc->btree_fd;
- concat(STEMP, Fileset, Mod_info.temp_sort);
- if ((sfp = fopen(Mod_info.temp_sort, "w")) == (char *)NULL)
- syserr("sort_isam: can't open %s", Mod_info.temp_sort);
- if ((fp = fopen(Mod_info.outfile, "r")) == NULL)
- syserr("sort_isam: can't open %s", Mod_info.outfile);
- for (i = 0; i < desc->reldum.reldim; lid[i++] = 0);
- /* create input file for sort with proper lid attached to each tuple */
- w = sdesc->reldum.relwid - LIDSIZE * sdesc->reldum.reldim;
- for ( ; ; )
- {
- i = fread(tup_buf, 1, sdesc->reldum.relwid, fp);
- if (i == 0)
- break;
- if (i != sdesc->reldum.relwid)
- syserr("sort_isam: read error in %s", Mod_info.outfile);
- for (j = 0; j < desc->reldum.reldim; ++j)
- if (j < NLidKeys && j < desc->reldum.reldim - 1)
- {
- dp = tup_buf + (sdesc->reloff[LidKey[j]] & I1MASK);
- sp = last_tup + (sdesc->reloff[LidKey[j]] & I1MASK);
- if (!bequal(dp, sp, sdesc->relfrml[LidKey[j]]) || !lid[j])
- {
- ++lid[j];
- for (k = j + 1; k < desc->reldum.reldim; ++k)
- lid[k] = 0;
- break;
- }
- }
- else
- {
- if (!lid[0])
- {
- lid[0] = 1;
- if (!(desc->reldum.reldim - 1))
- break;
- }
- ++lid[desc->reldum.reldim - 1];
- break;
- }
- bmove(tup_buf, last_tup, sdesc->reldum.relwid);
- /* reserve a slot in btree for tuple */
- insert_mbtree(desc, Mod_info.btree, lid, &tid, &tidpos);
- bmove(lid, tup_buf + w, LIDSIZE * desc->reldum.reldim);
- if (fwrite(tup_buf, 1, sdesc->reldum.relwid + LIDSIZE * desc->reldum.reldim, sfp) != sdesc->reldum.relwid + LIDSIZE * desc->reldum.reldim)
- syserr("sort_isam: write error in %s", Mod_info.temp_sort);
- }
- fclose(fp);
- fclose(sfp);
- /* set up new descriptor accounting for lid field */
- bmove(sdesc, &tempdesc, sizeof *sdesc);
- tempdesc.reldum.relspec = M_ORDER;
- for (i = 0; i < desc->reldum.reldim; ++i)
- {
- tempdesc.reldum.relwid += LIDSIZE;
- ++tempdesc.reldum.relatts;
- tempdesc.reloff[tempdesc.reldum.relatts] = tempdesc.reldum.relwid - LIDSIZE;
- tempdesc.relfrmt[tempdesc.reldum.relatts] = INT;
- tempdesc.relfrml[tempdesc.reldum.relatts] = LIDSIZE;
- }
- j = 0;
- /* use old keying attributes for specifying sort order */
- clearkeys(&tempdesc);
- for (i = 1; i <= sdesc->reldum.relatts; ++i)
- if (sdesc->relxtra[i])
- {
- tempdesc.relgiven[i] = sdesc->relxtra[i];
- ++j;
- }
- for (i = 1; i <= tempdesc.reldum.relatts; ++i)
- if (!tempdesc.relgiven[i])
- tempdesc.relgiven[i] = ++j;
- sortfile(Mod_info.temp_sort, &tempdesc, FALSE);
- if (unlink(Mod_info.outfile) < 0)
- syserr("can't unlink %s", Mod_info.outfile);
- if (link(ztack(REPL_OUT, Fileset), Mod_info.outfile) == -1)
- syserr("can't link %s to %s", ztack(REPL_OUT, Fileset), Mod_info.outfile);
- if (unlink(Mod_info.temp_sort) < 0)
- syserr("sort_isam: can't unlink %s", Mod_info.temp_sort);
- if (unlink(ztack(REPL_OUT, Fileset)) < 0)
- syserr("sort_isam: can't unlink replout file");
- }
- /*
- ** FILL_REL -- Fill the new relation with tuples from either
- ** the old relation or the output file of KSORT.
- */
-
- fill_rel(sdesc, desc, sortit)
- register DESC *sdesc, *desc;
- char sortit;
- {
- register int i;
- char tup_buf[MAXTUP], last_tup[MAXTUP], tup[2 * LIDSIZE];
- char junk[4], newreltype, anytups, chkdups;
- int need, j, k;
- long lnum, lid[MAXLID], l, page, t;
- TID tid, stid, stidlim, ntid, tidpos, btid;
- FILE *fp, *spfp;
- char *dp, *sp;
- int w, temp;
- struct locator tidloc;
-
- newreltype = abs(desc->reldum.relspec);
- if (sortit)
- {
- if ((fp = fopen(Mod_info.outfile, "r")) == NULL)
- syserr("FILL_REL: fopen %.14s", Mod_info.outfile);
- }
- else
- {
- cleanrel(sdesc); /* make sure each page is read fresh */
- find(sdesc, NOKEY, &stid, &stidlim);
- }
- if (newreltype == M_ISAM && (NLidKeys > 0 || !desc->reldum.reldim))
- {
- lnum = 0;
- stuff_page(&tid, &lnum);
- tid.line_id = 0;
- get_page(desc, &tid);
- concat(ISAM_SPOOL, Fileset, Mod_info.spfile);
- /* assume that spool file is not needed */
- spfp = NULL;
- Mod_info.spflag = FALSE;
- if (F_fac == 0)
- F_fac = 100;
- /* setup relgiven field for kcompare later on */
- for (i = 1; i <= desc->reldum.relatts; i++)
- desc->relgiven[i] = desc->relxtra[i];
- if (desc->reldum.reldim)
- Btree_fd = desc->btree_fd;
- }
- desc->reladds = 0;
- for (i = 0; i < desc->reldum.reldim; lid[i++] = 0)
- continue;
- anytups = FALSE;
- chkdups = !sortit && (newreltype != M_ORDER);
- # ifdef xZTR2
- if (tTf(36, 3))
- {
- printf(" FILLREL: ");
- printdesc(sdesc);
- printdesc(desc);
- }
- # endif
- for (;;)
- {
- w = (newreltype == M_ISAM) ? sdesc->reldum.relwid + desc->reldum.reldim * LIDSIZE : sdesc->reldum.relwid;
- if (sortit)
- {
- i = fread(tup_buf, 1, w, fp);
- if (i == 0)
- break;
- if (i != w)
- syserr("FILL_REL: fread A %d", i);
- if (newreltype == M_HASH && !desc->reldum.reldim)
- if (fread(junk, 1, 4, fp) != 4)
- syserr("FILL_REL: fread B");
- }
- else
- {
- # ifdef xZTR2
- if (tTf(36, 1))
- {
- printf("FILL_REL: stid ");
- dumptid(&stid);
- printf("FILL_REL: stidlim ");
- dumptid(&stidlim);
- }
- # endif
- i = get(sdesc, &stid, &stidlim, tup_buf, TRUE);
- # ifdef xZTR2
- if (tTf(36, 1))
- {
- printf("FILLREL: get %d ", i);
- printup(sdesc, tup_buf);
- }
- # endif
- if (i < 0)
- syserr("FILL_REL: get %d", i);
- if (i == 1)
- break;
- }
- if (newreltype != M_ISAM || (newreltype == M_ISAM && NLidKeys == 0 && desc->reldum.reldim > 0))
- {
- for (j = 0; j < desc->reldum.reldim; ++j)
- if (j < NLidKeys && j < desc->reldum.reldim - 1)
- {
- dp = tup_buf + (sdesc->reloff[LidKey[j]] & I1MASK);
- sp = last_tup + (sdesc->reloff[LidKey[j]] & I1MASK);
- if (!bequal(dp, sp, sdesc->relfrml[LidKey[j]]) || !lid[j])
- {
- ++lid[j];
- for (k = j + 1; k < desc->reldum.reldim; ++k)
- lid[k] = 0;
- break;
- }
- }
- else
- {
- if (!lid[0])
- {
- lid[0] = 1;
- if (!(desc->reldum.reldim -1))
- break;
- }
- ++lid[desc->reldum.reldim - 1];
- break;
- }
- Btree_fd = desc->btree_fd;
- if (!desc->reldum.reldim || NLidKeys > 0)
- {
- /* assume unordered so btree inserts done
- ** separately */
- temp = 0;
- if (desc->reldum.reldim > 0)
- {
- temp = desc->reldum.reldim;
- desc->reldum.reldim = 0;
- desc->reldum.relwid -= temp * LIDSIZE;
- }
- if ((i = insert(desc, &tid, tup_buf, chkdups)) < 0)
- syserr("FILL_REL: insert %d", i);
- if (NLidKeys > 0)
- {
- bmove(&tid, &stid, LIDSIZE);
- desc->reldum.reldim = temp;
- desc->reldum.relwid += temp * LIDSIZE;
- insert_mbtree(desc, Mod_info.btree, lid, &tid, &tidpos);
- }
- }
- if (desc->reldum.reldim && !NLidKeys)
- {
- /* new relation not changed, only lids added */
- page = RT;
- for (j = 0; j < desc->reldum.reldim - 1; ++j)
- {
- if (!lid[j])
- lid[j] = 1;
- if ((t = get_tid(page, lid[j], &tidloc)) < 0)
- {
- insert_btree(Mod_info.btree, page, lid[j], &ntid, &tidpos, j + 2);
- bmove(&ntid, &page, LIDSIZE);
- }
- else
- bmove(&t, &page, LIDSIZE);
- }
- insert_btree(Mod_info.btree, page, lid[abs(desc->reldum.reldim) - 1], &stid, &tidpos, FALSE);
- }
- bmove(tup_buf, last_tup, sdesc->reldum.relwid);
- if (desc->reldum.reldim > 0)
- {
- dp = tup_buf + desc->reldum.relwid - desc->reldum.reldim * LIDSIZE;
- bmove(lid, dp, LIDSIZE * desc->reldum.reldim);
- }
- # ifdef xZTR2
- if (tTf(36, 2))
- {
- printf("FILL_REL: insert ");
- printup(desc, tup_buf);
- printf("FILL_REL: insert ret %d at", i);
- dumptid(&tid);
- }
- # endif
- continue;
- }
- if (anytups)
- i = kcompare(desc, tup_buf, last_tup);
- else
- {
- anytups = TRUE;
- i = 1;
- }
- bmove(tup_buf, last_tup, desc->reldum.relwid);
- need = canonical(desc, tup_buf);
- if (i == 0 && need > space_left(Acc_head))
- {
- /* spool out this tuple. will go on overflow page later */
- if (spfp == NULL)
- {
- if ((spfp = fopen(Mod_info.spfile, "w")) == NULL)
- syserr("FILL_REL: fopen %.14s", Mod_info.spfile);
- Mod_info.spflag = TRUE;
- }
- if (fwrite(tup_buf, 1, desc->reldum.relwid, spfp) != desc->reldum.relwid)
- syserr("FILL_REL: putb spool");
- continue;
- }
- j = (100 - F_fac) * MAXTUP / 100;
- if (j < need)
- j = need;
- if (i != 0 && j > space_left(Acc_head))
- {
- if (i = add_prim(desc, &tid))
- syserr("FILL_REL: force ovflo %d", i);
- }
- tid.line_id = newlino(need);
- put_tuple(&tid, Acctuple, need);
- if (NLidKeys > 0)
- {
- bmove(tup_buf + desc->reldum.relwid - LIDSIZE * desc->reldum.reldim, lid, LIDSIZE * desc->reldum.reldim);
- page = RT;
- for (j = 0; j < desc->reldum.reldim; ++j)
- {
- if ((t = get_tid(page, lid[j], &tidloc)) < 0)
- syserr("get_tid error in modify isam ordered");
- page = t;
- }
- stuff_page(&btid, &tidloc.pageno);
- btid.line_id = tidloc.page.node.leafnode.tid_loc[tidloc.offset];
- /* place proper tid in tree */
- replace_btree(tid, &btid);
- }
- desc->reladds++;
- }
- if (sortit)
- {
- fclose(fp);
- unlink(Mod_info.outfile);
- }
- if (newreltype == M_ISAM && desc->reldum.reldim <= 0)
- {
- if (i = pageflush(Acc_head))
- syserr("fill_rel:pg clean %d", i);
- if (spfp != NULL)
- fclose(spfp);
- }
- if (!desc->reldum.reldim || NLidKeys > 0)
- desc->reldum.reltups = desc->reladds;
- desc->reladds = 0;
- return (0);
- }
-
-
- /*
- ** BLDINDEX -
- **
- ** Parameters:
- ** d - descriptor for relation
- **
- ** Return Codes:
- ** 0 - ok
- ** <0 - error
- **
- ** Trace Flags:
- ** Z38.7, Z38.8
- **
- ** Called by:
- ** modify
- **
- */
- bldindex(d)
- register DESC *d;
- {
- register TID *tid;
- register int tmp;
- TID tidx;
- struct accbuf dirbuf;
- int keywid, level, savespec, keyx[MAXDOM];
- int offset, len;
- char tuple[MAXTUP], temptup[MAXTUP], *key;
- long pageid, start, stop, newstart, newstop;
-
- tid = &tidx;
- keywid = 0;
- for (tmp = 0; tmp < MAXDOM; tmp++)
- keyx[tmp] = 0;
- for (tmp = 1; tmp <= d->reldum.relatts; tmp++)
- if (d->relxtra[tmp] > 0)
- {
- keyx[d->relxtra[tmp] - 1] = tmp;
- keywid += d->relfrml[tmp] & I1MASK;
- }
-
- /* Determine the last page of the relation. This will
- ** only work if all pages have been written out. Fill_rel
- ** must guarantee that all pages have been written
- */
- level = 0;
- last_page(d, tid, 0);
- pluck_page(tid, &stop);
- start = 0;
- dirbuf.filedesc = d->relfp;
- dirbuf.rel_tupid = d->reltid.ltid;
- savespec = d->reldum.relspec;
- for (;;)
- {
- # ifdef xZTR2
- if (tTf(38, 7))
- printf("isam: level %d\n", level);
- # endif
- dirbuf.ovflopg = start;
- dirbuf.mainpg = level;
- dirbuf.thispage = stop + 1;
- dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf);
- offset = dirbuf.linetab[0];
- dirbuf.bufstatus = BUF_DIRTY | BUF_DIRECT;
-
- dirbuf.nxtlino = 0;
- newstart = stop + 1;
- newstop = newstart;
- for (pageid = start; pageid <= stop; pageid++)
- {
- # ifdef xZTR2
- if (tTf(38, 8))
- printf("isam:get key from %ld\n", pageid);
- # endif
- stuff_page(tid, &pageid);
- tid->line_id = 0;
- if (tmp = get(d, tid, tid, tuple, FALSE))
- {
- /*
- ** If the relation is empty, then page 0 will
- ** return AMINVL_ERR on a get(). Form a blank tuple
- ** and use it to create a one tuple directory
- */
- if (pageid == 0 && tmp == AMINVL_ERR)
- {
- clr_tuple(d, tuple);
- }
- else
- {
- return (-2);
- }
- }
-
- /*
- ** If this is the first level then form the tuple
- ** from the mainpage of the relation. Otherwise
- ** the tuple is the first tuple of a directory page
- ** and it is already correctly formed.
- */
- if (level == 0)
- {
- key = temptup;
- for (tmp = 0; keyx[tmp] != 0; tmp++)
- {
- len = d->relfrml[keyx[tmp]] & I1MASK;
- bmove(&tuple[d->reloff[keyx[tmp]]], key, len);
- key += len;
- }
- key = temptup;
- }
- else
- key = tuple;
-
- if (keywid > space_left(&dirbuf))
- {
- if (pageflush(&dirbuf))
- return (-3);
- dirbuf.thispage++;
- newstop = dirbuf.thispage;
- dirbuf.ovflopg = pageid;
- dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf);
- offset = dirbuf.linetab[0];
- dirbuf.bufstatus = BUF_DIRTY;
- dirbuf.nxtlino = 0;
- }
- /* copy key to directory page */
- bmove(key, (char *) &dirbuf + offset, keywid);
-
- /* update next line number */
- offset += keywid;
- dirbuf.nxtlino++;
- dirbuf.linetab[-dirbuf.nxtlino] = offset;
- }
- if (pageflush(&dirbuf))
- return (-4);
- if (newstart == newstop)
- break;
- d->reldum.relspec = abs(d->reldum.relspec);
- level++;
- start = newstart;
- stop = newstop;
- }
- d->reldum.relspec = savespec;
- d->reldum.relprim = newstart;
- return (0);
- }
- /*
- ** UNSPOOL -- Take tuples saved in spool file and insert them
- ** in new relation. This is only for ISAM relations.
- */
-
- unspool(sdesc, desc)
- register DESC *sdesc, *desc;
- {
- register int i, j;
- TID tid, btid;
- char tup_buf[MAXTUP], tup[2 * LIDSIZE];
- FILE *spfp;
- long lid[MAXLID], page, t;
- int w;
- struct locator tidpos;
-
- w = sdesc->reldum.relwid + desc->reldum.reldim * LIDSIZE;
- if (Mod_info.spflag)
- {
- if ((spfp = fopen(Mod_info.spfile, "r")) == NULL)
- syserr("UNSPOOL: fopen spool");
- while ((i = fread(tup_buf, 1, w, spfp)) == w)
- {
- if ((i = insert(desc, &tid, tup_buf, FALSE)) < 0)
- syserr("UNSPOOL: insert %.14s %d", desc->reldum.relid, i);
- if (NLidKeys > 0)
- {
- bmove(tup_buf + desc->reldum.relwid - LIDSIZE * desc->reldum.reldim, lid, LIDSIZE * desc->reldum.reldim);
- page = RT;
- for (j = 0; j < desc->reldum.reldim; ++j)
- {
- if ((t = get_tid(page, lid[j], &tidpos)) < 0)
- syserr("get_tid error in unspool");
- page = t;
- }
- stuff_page(&btid, &tidpos.pageno);
- btid.line_id = tidpos.page.node.leafnode.tid_loc[tidpos.offset];
- replace_btree(tid, &btid);
- }
- }
- if (i != 0)
- syserr("UNSPOOL: read %d", i);
- fclose(spfp);
- unlink(Mod_info.spfile);
- }
- desc->reldum.reltups += desc->reladds;
- desc->reladds = 0;
- return (0);
- }
- /*
- ** FILL_BATCH -- Create and fill a batch file containing the
- ** updates for the system catalog so that MODIFY will
- ** be recoverable if the system crashes.
- */
-
- fill_batch(odesc, desc)
- DESC *odesc;
- register DESC *desc;
- {
- register DESC *dessys;
- register int i, k;
- struct relation reltup, rkey;
- TID tid, lotid, hitid;
- struct attribute atttup, akey;
- int numatts, j;
- char prebatch[MAXNAME + 4], modbatch[MAXNAME + 4];
-
- if (bequal(desc->reldum.relid, "relation ", 12))
- {
- clearkeys(desc);
- setkey(desc, &rkey, desc->reldum.relid, RELID);
- setkey(desc, &rkey, desc->reldum.relowner, RELOWNER);
- if (i = getequal(desc, &rkey, &reltup, &tid))
- syserr("FILL_BATCH: geteq rel rel %d", i);
- bmove(&tid, &desc->reltid, sizeof desc->reltid);
- }
- else
- bmove(&odesc->reltid, &desc->reltid, sizeof desc->reltid);
- resetacc(Acc_head);
- concat(MOD_PREBATCH, Fileset, prebatch);
- close(creat(prebatch, FILEMODE));
- if ((Batch_fp = open(prebatch, O_RDWR)) < 0)
- syserr("FILL_BATCH: open %.14s %d", prebatch, Batch_fp);
- smove(Fileset, Batchbuf.file_id);
- Batch_cnt = 0;
- wrbatch(desc, sizeof *desc);
- if (bequal(desc->reldum.relid, "attribute ", 12))
- dessys = desc;
- else
- dessys = &Admin.adattd;
- clearkeys(dessys);
- setkey(dessys, &akey, desc->reldum.relid, ATTRELID);
- setkey(dessys, &akey, desc->reldum.relowner, ATTOWNER);
- if (i = find(dessys, EXACTKEY, &lotid, &hitid, &akey))
- syserr("FILL_BATCH: find %d", i);
-
- /* if ordered relation, one of attributes is LID field */
- numatts = j = desc->reldum.relatts - desc->reldum.reldim;
-
- while(!(i = get(dessys, &lotid, &hitid, &atttup, TRUE)) && j > 0)
- if (!kcompare(dessys, &akey, &atttup))
- if (atttup.attid <= numatts)
- {
- j--;
- atttup.attxtra = desc->relxtra[atttup.attid];
- wrbatch(&lotid, sizeof lotid);
- wrbatch(&atttup, sizeof atttup);
- }
- for (k = 1; k <= desc->reldum.reldim; ++k)
- /* create new tuple corresponding to LID field; LID field is the
- ** last field of relation, a 4-byte integer
- */
- {
- smove(desc->reldum.relid, atttup.attrelid);
- bmove(desc->reldum.relowner, atttup.attowner, 2);
- atttup.attid = numatts + k;
- smove(Lid[k - 1], atttup.attname);
- pad(atttup.attname, MAXNAME);
- atttup.attoff = desc->reldum.relwid - (desc->reldum.reldim - k + 1) * LIDSIZE;
- atttup.attfrmt = INT;
- atttup.attfrml = LIDSIZE;
- atttup.attxtra = 0;
- wrbatch(&atttup, sizeof atttup);
- }
- if (i < 0 || j > 0)
- syserr("FILL_BATCH: get att %d count %d", i, j);
- /* get rid of attribute pages */
- cleanrel(dessys);
- flushbatch();
- close(Batch_fp);
- concat(MODBATCH, Fileset, modbatch);
- if (link(prebatch, modbatch) == -1)
- syserr("FILL_BATCH: can't link %.14s %.14s",
- prebatch, modbatch);
- unlink(prebatch);
- return (0);
-
- }
-
- /*
- ** MAKE_BSEC -- Creates the seecondary btree relation by first creating
- ** a heaped relation. The main relation tids are found by
- ** scanning the leaves of the btree. The relation is then
- ** modified to an isam relation.
- */
-
- make_bsec(relname, dim)
- char *relname;
- int dim;
- {
- PARM pv[8];
- register int i;
- DESC bdesc;
- TID tid, btid;
- long mtid, page, t, next;
- char tuple[2 * LIDSIZE], btree[MAXNAME], btreefile[MAXNAME + 4];
- struct locator tidpos;
- extern char *iocv();
- extern DESC Reldes;
-
- pv[0].pv_val.pv_str = "0000002";
- capital(trim_relname(relname), btree);
- pv[1].pv_val.pv_str = btree;
- pv[2].pv_val.pv_str = "mtid";
- pv[3].pv_val.pv_str = "i4";
- pv[4].pv_val.pv_str = "btid";
- pv[5].pv_val.pv_str = "i4";
- pv[6].pv_type = PV_EOF;
- if (create(6, pv))
- syserr("can't create btreesec %s", pv[1].pv_val.pv_str);
-
- if (noclose(&Reldes))
- syserr("noclose in make_bsec");
-
- if (i = openr(&bdesc, OR_WRITE, btree))
- syserr("opening bsec relation %d", i);
- btreename(relname, btreefile);
- if ((Btree_fd = open(btreefile, O_RDWR)) < 0)
- syserr("make_bsec: can't open %s", btreefile);
- page = RT;
- for (i = 0; i < dim - 1; ++i)
- {
- t = get_tid(page, 1, &tidpos);
- if (t < 0)
- break; /* lid value doesn't exist */
- bmove(&t, &page, LIDSIZE);
- }
- if (t >= 0) /* only do inserts if there are lids! */
- {
- do
- {
- get_node(page, &tidpos.page);
- next = tidpos.page.nexttree;
- get_tid(page, 1, &tidpos);
- page = tidpos.pageno;
- for (;;)
- /* scan through leaves of btree */
- {
- stuff_page(&btid, &page);
- for (i = 0; i < tidpos.page.nelmts; ++i)
- {
- btid.line_id = tidpos.page.node.leafnode.tid_loc[i];
- mtid = tidpos.page.node.leafnode.tid_pos[btid.line_id];
- /* form tuple */
- bmove(&mtid, tuple, LIDSIZE);
- bmove(&btid, tuple + LIDSIZE, LIDSIZE);
- if (insert(&bdesc, &tid, tuple, TRUE) < 0)
- syserr("insert error in btreesec");
- }
- page = tidpos.page.node.leafnode.nextleaf;
- if (page == NULL)
- break;
- else
- get_node(page, &tidpos.page);
- }
- } while (page = next);
- }
- close(Btree_fd);
- closer(&bdesc);
-
- /* modify to isam on mtid */
- pv[0].pv_val.pv_str = btree;
- pv[1].pv_val.pv_str = "isam";
- pv[2].pv_val.pv_str = "name";
- pv[3].pv_val.pv_str = "mtid";
- pv[4].pv_val.pv_str = "\0";
- pv[5].pv_val.pv_str = "fillfactor";
- /* use fillfactor provided for main relation */
- if (F_fac == 0)
- pv[6].pv_val.pv_str = iocv(80);
- else
- pv[6].pv_val.pv_str = iocv(F_fac);
- pv[7].pv_type = PV_EOF;
- if (modify(7, pv))
- syserr("can't modify btreesec to isam");
- }
-